﻿using AIVision.Model.MachineModels;
using AIVision.Model.EntityModels;
using AIVision.Model.UIModels;
using AIVision.PLC.LiWi;
using ImTools;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Automation;

namespace AIVision.PLC.MachineModule
{
    public class ChaHe
    {
        private readonly ChaHeStatusModel chaHeStatus;
        private readonly IEventAggregator eventAggregator;
        private readonly MachineStatusModel machineStatus;
        private IntPtr _handle;
        private PLCConfigDto plcConfig;
       
        public Task RunTask { get; set; } = new Task(() => { });
        
        

        #region X
        public bool XStartXH
        {
            get
            {
                uint in12 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 12, ref in12);
                return in12 == 1;
            }
        }
        public bool XEndXH
        {
            get
            {
                uint in11 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 11, ref in11);
                return in11 == 1;
            }
        }

        public bool QuLiaoUpXH
        {
            get
            {
                uint in13 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 13, ref in13);
                chaHeStatus.QuLiaoUpXH = in13 == 1;
                return in13 == 1;
            }
        }
        public bool QuLiaoDownXH
        {
            get
            {
                uint in14 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 14, ref in14);
                chaHeStatus.QuLiaoDownXH = in14 == 1;
                return in14 == 1;
            }
        }

        public bool QuLiaoOKXH
        {
            get
            {
                uint in15 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 15, ref in15);
                chaHeStatus.QuLiaoOKXH = in15 == 1;
                return in15 == 1;
            }
        }
        public int XLocation
        {
            get
            {
                float dpos = 0;
                Shell.PMC_GetDpos(_handle, 5, ref dpos);
                int v;
                if (dpos == plcConfig.ChaHeXZeroLocation)
                    v = 0;
                else if (dpos == plcConfig.ChaHeXFirstLocation)
                    v = 1;
                else
                {
                    if (dpos > plcConfig.ChaHeXFirstLocation)
                    {
                        var v1 = dpos - plcConfig.ChaHeXFirstLocation;
                        var v2 = v1 / plcConfig.ChaHeXStep;
                        v = (int)Math.Floor(v2) + 1;
                    }
                    else
                        v = -1;


                }
                chaHeStatus.XLocation = v;
                return v;
            }
        }
        public int XRecordLocation { get; set; }
        public bool XServoRunXH
        {
            get
            {
                int runFlag = -1;
                Shell.PMC_GetIfIdle(_handle, 5, ref runFlag);
                chaHeStatus.XServoRunXH = runFlag == 0;
                return runFlag == 0;
            }
        } 
        #endregion

        #region Y
        public bool YStartXH
        {
            get
            {
                uint in17 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 17, ref in17);
                //chaHeStatus.QuLiaoOKXH = in17 == 1;
                return in17 == 1;
            }
        }
        public int YLocation
        {
            get
            {
                float dpos = 0;
                Shell.PMC_GetDpos(_handle, 4, ref dpos);
                int v;
                if (dpos == plcConfig.ChaHeYZeroLocation)
                    v = 0;
                else if (dpos == plcConfig.ChaHeYFirstLocation)
                    v = 1;
                else if (dpos == plcConfig.ChaHeYLastLocation)
                    v = 99;
                else
                {
                    if (dpos > plcConfig.ChaHeYFirstLocation)
                    {
                        var v1 = dpos - plcConfig.ChaHeYFirstLocation;
                        var v2 = v1 / plcConfig.ChaHeYStep;
                        var v3 = v1 % plcConfig.ChaHeYStep;
                        if (v3 == 0)
                            v = (int)Math.Floor(v2) + 1;
                        else
                            v = -1;
                    }
                    else
                        v = -1;


                }
                chaHeStatus.YLocation = v;
                return v;
            }
        }
        public int YRecordLocation { get; set; }
        public bool QuHe1UpXH
        {
            get
            {
                uint in20 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 20, ref in20);
                //chaHeStatus.QuLiaoUpXH = in20 == 1;
                return in20 == 1;
            }
        }
        public bool QuHe1DownXH
        {
            get
            {
                uint in21 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 21, ref in21);
                //chaHeStatus.QuLiaoUpXH = in21 == 1;
                return in21 == 1;
            }
        }

        public bool QuHe2UpXH
        {
            get
            {
                uint in18 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 18, ref in18);
                //chaHeStatus.QuLiaoUpXH = in18 == 1;
                return in18 == 1;
            }
        }
        public bool QuHe2DownXH
        {
            get
            {
                uint in19 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 19, ref in19);
                //chaHeStatus.QuLiaoUpXH = in19 == 1;
                return in19 == 1;
            }
        }

        public bool JiaHe1ChuXH
        {
            get
            {
                uint in22 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 22, ref in22);
                //chaHeStatus.QuLiaoUpXH = in22 == 1;
                return in22 == 1;
            }
        }
        public bool JiaHe1HuiXH
        {
            get
            {
                uint in23 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 23, ref in23);
                //chaHeStatus.QuLiaoUpXH = in23 == 1;
                return in23 == 1;
            }
        }
        public bool TuiHeUpXH
        {
            get
            {
                uint in24 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 24, ref in24);
                //chaHeStatus.QuLiaoUpXH = in22 == 1;
                return in24 == 1;
            }
        }
        public bool TuiHeDownXH
        {
            get
            {
                uint in25 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 25, ref in25);
                //chaHeStatus.QuLiaoUpXH = in22 == 1;
                return in25 == 1;
            }
        }
        public bool TuiHeHuiXH
        {
            get
            {
                uint in16 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 16, ref in16);
                //chaHeStatus.QuLiaoUpXH = in22 == 1;
                return in16 == 1;
            }
        }
        public bool HeJianCeXH
        {
            get
            {
                uint in26 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 26, ref in26);
                chaHeStatus.HeJianCeXH = in26 == 1;
                return in26 == 1;
            }
        }
        public bool HeBuZuXH
        {
            get
            {
                uint in27 = 0;
                LiWi.Shell.PMC_GetIn(_handle, 27, ref in27);
                chaHeStatus.HeBuZuXH = in27 == 1;
                return in27 == 1;
            }
        }
        public bool YServoRunXH
        {
            get
            {
                int runFlag = -1;
                Shell.PMC_GetIfIdle(_handle, 4, ref runFlag);
                chaHeStatus.YServoRunXH = runFlag == 0;
                return runFlag == 0;
            }
        } 
        #endregion

        #region Init
        public ChaHe(ChaHeStatusModel chaHeStatus, IEventAggregator eventAggregator,MachineStatusModel machineStatus)
        {
            this.chaHeStatus = chaHeStatus;
            this.eventAggregator = eventAggregator;
            this.machineStatus = machineStatus;
        }
        public void Init(IntPtr _handle, PLCConfigDto plcConfig)
        {
            this._handle = _handle;
            this.plcConfig = plcConfig;
        }
        public void MonitorStatus()
        {
            float dpos = 0, mpos = 0, pfvalue = 0;
            Shell.PMC_GetDpos(_handle, 5, ref dpos);
            Shell.PMC_GetMpos(_handle, 5, ref mpos);
            Shell.PMC_GetMspeed(_handle, 5, ref pfvalue);
            chaHeStatus.XDPos = dpos;
            chaHeStatus.XMPos = mpos;
            chaHeStatus.XSpeed = pfvalue;
            Shell.PMC_GetDpos(_handle, 4, ref dpos);
            Shell.PMC_GetMpos(_handle, 4, ref mpos);
            Shell.PMC_GetMspeed(_handle, 4, ref pfvalue);
            chaHeStatus.YDPos = dpos;
            chaHeStatus.YMPos = mpos;
            chaHeStatus.YSpeed = pfvalue;
            var v = QuLiaoUpXH;
            v = QuLiaoDownXH;
            v = QuLiaoOKXH;
            v = HeJianCeXH;
            v = XServoRunXH;
            v = YServoRunXH;
            int i = XLocation;
            i = YLocation;
            if(HeBuZuXH) //盒不足，报警。
                LiWi.Shell.PMC_SetOp(_handle, 23, 1);
            else
                LiWi.Shell.PMC_SetOp(_handle, 23, 0);
        }
        #endregion

        public void RunAsync()
        {
            if (RunTask.Status != TaskStatus.Running)
            {
                CTS = new CancellationTokenSource();
                RunTask = new Task(Run, CTS.Token);
                RunTask.Start();
            }
        }
        public void Run()
        {
            if (XLocation != 0 || !QuLiaoUpXH || machineStatus.EmergencyStopXH)
                return;
            ChaHeXStep1();
            ChaHeXStep2();
        }

        #region X轴
        public void ResetXLocationAsync()
        {
            if (RunTask.Status != TaskStatus.Running && !machineStatus.EmergencyStopXH)
            {
                CTS = new CancellationTokenSource();
                RunTask = new Task(ResetXLocation,CTS.Token);
                RunTask.Start();
            }
        }
        public void ResetXLocation()
        {
            if (machineStatus.EmergencyStopXH)
                return;
            try
            {
                LiWi.Shell.PMC_SetOp(_handle, 1, 0); //吸嘴先上来
                timeout = 0;
                while (!QuLiaoUpXH)
                    WaitTimeout(1000);
                LiWi.Shell.PMC_SetOp(_handle, 2, 0); //吸料
                XRecordLocation = 0;


                int ret0 = Shell.PMC_SetAtype(_handle, 5, 1); // 设置轴 0 轴类型为 1 
                ret0 += Shell.PMC_SetInvertStep(_handle, 5, 1);
                ret0 += Shell.PMC_SetUnits(_handle, 5, 1); // 设置轴 0 脉冲当量为 100 
                Shell.PMC_SetAxisEnable(_handle, 5, 1);

                if (!XStartXH)
                {
                    Shell.PMC_SetSpeed(_handle, 5, 3600); // 设置轴 0 速度为 200units/s 
                    Shell.PMC_Single_Vmove(_handle, 5, -1);
                    timeout = 0;
                    while (!XStartXH)
                        WaitTimeout(3000, "插盒X轴回原点");
                    Shell.PMC_Single_Cancel(_handle, 5, 3);
                }
                if (XStartXH)
                {
                    Shell.PMC_SetSpeed(_handle, 5, 180); // 设置轴 0 速度为 200units/s 

                    Shell.PMC_Single_Vmove(_handle, 5, -1);
                    timeout = 0;
                    while (XStartXH)
                        WaitTimeout(3000);
                    Shell.PMC_Single_Cancel(_handle, 5, 3);
                }
                Shell.PMC_SetDpos(_handle, 5, 0); // 轴指令位置清 0 
                Shell.PMC_SetMpos(_handle, 5, 0); // 编码器反馈位置清 0 
                Shell.PMC_SetSpeed(_handle, 5, plcConfig.ChaHeXRunSpeed); // 设置轴 0 速度为 200units/s 
                Shell.PMC_SetAccel(_handle, 5, plcConfig.ChanheXAccl); // 设置轴 0 加速度为 2000units/s/s 
                Shell.PMC_SetDecel(_handle, 5, plcConfig.ChanheXAccl); // 设置轴 0 减速度为 2000units/s/s 
                LiWi.Shell.PMC_SetSramp(_handle, 5, 50);
                LiWi.Shell.PMC_Single_MoveAbs(_handle, 5, plcConfig.ChaHeXZeroLocation);
            }
            catch (OperationCanceledException)
            {
                Shell.PMC_Single_Cancel(_handle, 5, 3);
            }
        }



        public void ChaHeXStepAsync()
        {
            if (RunTask.Status != TaskStatus.Running && !machineStatus.EmergencyStopXH && machineStatus.ResetLocationStatus)
            {
                CTS = new CancellationTokenSource();
                RunTask = new Task(ChaHeXStep, CTS.Token);
                RunTask.Start();
            }
        }
        public void ChaHeXStep()
        {
            if (!QuLiaoUpXH && machineStatus.EmergencyStopXH && !machineStatus.ResetLocationStatus)
                return;
            if (XLocation == 0)
                ChaHeXStep1();
            else
                ChaHeXStep2();
        }

        private void ChaHeXStep1()
        {
            try
            {
                Task.Delay(plcConfig.OKQuDelay).Wait();
                LiWi.Shell.PMC_SetOp(_handle, 1, 1);  //气缸下
                timeout = 0;
                while (!QuLiaoDownXH)                                //等待
                    WaitTimeout(1000);                        //等待
                LiWi.Shell.PMC_SetOp(_handle, 2, 1); //吸料
                timeout = 0;
                while (!QuLiaoOKXH)
                    WaitTimeout(1000, timeOutDelegate: () =>
                    {
                        LiWi.Shell.PMC_SetOp(_handle, 2, 0); //吸料
                        LiWi.Shell.PMC_SetOp(_handle, 1, 0);  //气缸上
                    });
                LiWi.Shell.PMC_SetOp(_handle, 1, 0);  //气缸上
                timeout = 0;
                while (!QuLiaoUpXH)                                //等待
                    WaitTimeout(1000);
                XRecordLocation += 1;                                      //计算摆放位置

                if (XRecordLocation > plcConfig.ChaHeXCount)
                {
                    XRecordLocation = 1;
                    ChaHeYStep();
                }

                float location = plcConfig.ChaHeXFirstLocation + ((XRecordLocation - 1) * plcConfig.ChaHeXStep);
                LiWi.Shell.PMC_Single_MoveAbs(_handle, 5, location);   //直线导轨
                timeout = 0;
                while (XServoRunXH)                     //等待
                    WaitTimeout(1000);
            }
            catch (OperationCanceledException)
            {
                Shell.PMC_Single_Cancel(_handle, 5, 3);
            }
        }
        private void ChaHeXStep2()
        {
            try
            {
                Task.Delay(plcConfig.ChaHeXUpDelay).Wait();
                LiWi.Shell.PMC_SetOp(_handle, 1, 1);  //气缸下
                timeout = 0;
                while (!QuLiaoDownXH)                           //等待
                    WaitTimeout(1000);
                LiWi.Shell.PMC_SetOp(_handle, 2, 0); //放料
                Task.Delay(plcConfig.ChaHeXDownDelay).Wait();                           //放料延时
                LiWi.Shell.PMC_SetOp(_handle, 1, 0);   //气缸上
                timeout = 0;
                while (!QuLiaoUpXH)                                 //等待
                    WaitTimeout(1000);
                LiWi.Shell.PMC_Single_MoveAbs(_handle, 5, plcConfig.ChaHeXZeroLocation);  //回零位
                timeout = 0;
                while (XLocation != 0)
                    WaitTimeout(5000);
            }
            catch (OperationCanceledException)
            {
                Shell.PMC_Single_Cancel(_handle, 5, 3);
            }
        }
        #endregion

        #region Y轴
        public void ResetYLocationAsync()
        {
            if (RunTask.Status != TaskStatus.Running && !machineStatus.EmergencyStopXH)
            {
                CTS = new CancellationTokenSource();
                RunTask = new Task(ResetYLocation,CTS.Token);
                RunTask.Start();
            }
        }
        public void ResetYLocation()
        {
            if (machineStatus.EmergencyStopXH)
                return;
            try
            {
                int ret0 = Shell.PMC_SetAtype(_handle, 4, 1); // 设置轴 0 轴类型为 1 
                ret0 += Shell.PMC_SetInvertStep(_handle, 4, 1);
                ret0 += Shell.PMC_SetUnits(_handle, 4, 10); // 设置轴 0 脉冲当量为 100 
                Shell.PMC_SetAxisEnable(_handle, 4, 0);

                JiaHe1Do(false);
                JiaHe2Do(false);
                QuHe1Do(false);
                QuHe2Do(false);
                TuiHeUpDo(false);
                TuiHeOut(false);
                ChaHeYStep1();
                ChaHeYStep3();
                ChaHeYStep1();
            }
            catch (OperationCanceledException)
            {
                Shell.PMC_Single_Cancel(_handle, 4, 3);
            }
        }

        public void ChaHeYStepAsync()
        {
            if (RunTask.Status != TaskStatus.Running && !machineStatus.EmergencyStopXH && machineStatus.ResetLocationStatus)
            {
                CTS = new CancellationTokenSource();
                RunTask = new Task(ChaHeYStep, CTS.Token);
                RunTask.Start();
            }
        }
        public void ChaHeYStep()
        {
            if (machineStatus.EmergencyStopXH && ! machineStatus.ResetLocationStatus)
                return;
            try
            {
                if (machineStatus.CompleteInspect && machineStatus.VirtuallyXHCount == 8)
                {
                    ChaHeYStep3();
                    ChaHeYStep1();
                }
                else if (YLocation==0 || YLocation == -1 || YLocation == 99)
                {
                    ChaHeYStep1();
                }
                else if (YLocation > 0 && YLocation < plcConfig.ChaHeYCount)
                {
                    ChaHeYStep2();
                }
                else if (YLocation == plcConfig.ChaHeYCount)
                {
                    ChaHeYStep3();
                    ChaHeYStep1();
                }
            }
            catch (OperationCanceledException)
            {
                Shell.PMC_Single_Cancel(_handle, 4, 3);
            }
        }

        private void ChaHeYStep1()
        {
            CTS.Token.ThrowIfCancellationRequested();
            int timeout = 0;
            if (!YStartXH)
            {
                Shell.PMC_SetSpeed(_handle, 4, plcConfig.ChaHeYRunSpeed); // 设置轴 0 速度为 200units/s 
                Shell.PMC_SetAccel(_handle, 4, plcConfig.ChanheYAccl); // 设置轴 0 加速度为 2000units/s/s 
                Shell.PMC_SetDecel(_handle, 4, plcConfig.ChanheYAccl); // 设置轴 0 减速度为 2000units/s/s 
                Shell.PMC_Single_Vmove(_handle, 4, -1);
                timeout = 0;
                while (!YStartXH)
                    WaitTimeout(5000);
                Shell.PMC_Single_Cancel(_handle, 4, 3);
            }
            if (YStartXH)
            {
                Shell.PMC_SetSpeed(_handle, 4, 100); // 设置轴 0 速度为 200units/s 
                Shell.PMC_SetAccel(_handle, 4, plcConfig.ChanheYAccl); // 设置轴 0 加速度为 2000units/s/s 
                Shell.PMC_SetDecel(_handle, 4, plcConfig.ChanheYAccl); // 设置轴 0 减速度为 2000units/s/s
                Shell.PMC_Single_Vmove(_handle, 4, -1);
                timeout = 0;
                while (YStartXH)
                    WaitTimeout(3000);
                Shell.PMC_Single_Cancel(_handle, 4, 3);
            }
            Shell.PMC_SetDpos(_handle, 4, 0); // 轴指令位置清 0 
            Shell.PMC_SetMpos(_handle, 4, 0); // 编码器反馈位置清 0 
            Shell.PMC_SetSpeed(_handle, 4, plcConfig.ChaHeYRunSpeed); // 设置轴 0 速度为 200units/s 
            Shell.PMC_SetAccel(_handle, 4, plcConfig.ChanheYAccl); // 设置轴 0 加速度为 2000units/s/s 
            Shell.PMC_SetDecel(_handle, 4, plcConfig.ChanheYAccl); // 设置轴 0 减速度为 2000units/s/s 
            Shell.PMC_Single_MoveAbs(_handle, 4, plcConfig.ChaHeYZeroLocation);
            timeout = 0;
            while (YServoRunXH)
                WaitTimeout(3000);
            if (!HeJianCeXH)
            {
                CTS.Token.ThrowIfCancellationRequested();
                QuHe1Do(true);
                QuHe2Do(true);
                JiaHe1Do(true);
                JiaHe2Do(true);
                QuHe2Do(false);
                Task.Delay(500).Wait();
                JiaHe1Do(false);
                QuHe1Do(false);
                JiaHe2Do(false);
                timeout = 0;
                while (!HeJianCeXH)
                    WaitTimeout(3000, "取盒检测!");
            }
            CTS.Token.ThrowIfCancellationRequested();
            LiWi.Shell.PMC_Single_MoveAbs(_handle, 4, plcConfig.ChaHeYFirstLocation);   //直线导轨
            timeout = 0;
            while (YServoRunXH)
                WaitTimeout(3000);


        }
        private void ChaHeYStep2()
        {
            int next = YLocation + 1;
            float location = plcConfig.ChaHeYFirstLocation + ((next - 1) * plcConfig.ChaHeYStep);
            LiWi.Shell.PMC_Single_MoveAbs(_handle, 4, location);   //直线导轨
            timeout = 0;
            while (YServoRunXH)
                WaitTimeout(3000);
        }
        private void ChaHeYStep3()
        {
            LiWi.Shell.PMC_Single_MoveAbs(_handle, 4, plcConfig.ChaHeYLastLocation);   //直线导轨
            timeout = 0;
            while(YServoRunXH)
                WaitTimeout(60000);
            TuiHeUpDo(true);
            Task.Run(() =>
            {
                TuiHeOut(true);
                TuiHeOut(false);
                TuiHeUpDo(false);
            });
            
        }
        #region Y轴气缸动作
        private void QuHe1Do(bool b)
        {
            int i = 0;
            if (b && QuHe1DownXH)  //上
            {
                LiWi.Shell.PMC_SetOp(_handle, 8, 1);
                Task.Delay(plcConfig.QuHe1Delay).Wait();
                while (!QuHe1UpXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
            else if (!b && QuHe1UpXH) //下
            {
                LiWi.Shell.PMC_SetOp(_handle, 8, 0);
                Task.Delay(plcConfig.QuHe1Delay).Wait();
                while (!QuHe1UpXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
        }
        private void QuHe2Do(bool b)
        {
            int i = 0;
            if (b && QuHe2DownXH)  //上
            {
                LiWi.Shell.PMC_SetOp(_handle, 7, 1);
                Task.Delay(plcConfig.QuHe2Delay).Wait();
                while (!QuHe2UpXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
            else if (!b && QuHe2UpXH) //下
            {
                LiWi.Shell.PMC_SetOp(_handle, 7, 0);
                Task.Delay(plcConfig.QuHe2Delay).Wait();
                while (!QuHe2UpXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
        }
        private void JiaHe1Do(bool b)
        {
            int i = 0;
            if (!b && JiaHe1HuiXH)  //上
            {
                LiWi.Shell.PMC_SetOp(_handle, 6, 0);
                Task.Delay(plcConfig.JiaHe1Delay).Wait();
                while (!JiaHe1ChuXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
            else if (b && JiaHe1ChuXH) //下
            {
                LiWi.Shell.PMC_SetOp(_handle, 6, 1);
                Task.Delay(plcConfig.JiaHe1Delay).Wait();
                while (!JiaHe1HuiXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
        }
        private void JiaHe2Do(bool b)
        {
            if (b)  //出
            {
                Task.Delay(plcConfig.JiaHe2Delay).Wait();
                LiWi.Shell.PMC_SetOp(_handle, 15, 1);
                Task.Delay(plcConfig.JiaHe2Delay).Wait();
            }
            else  //回
            {
                Task.Delay(plcConfig.JiaHe2Delay).Wait();
                LiWi.Shell.PMC_SetOp(_handle, 15, 0);
                Task.Delay(plcConfig.JiaHe2Delay).Wait();
            }
        }
        private void TuiHeUpDo(bool b)
        {
            int i = 0;
            if (b && TuiHeDownXH)  //上
            {
                LiWi.Shell.PMC_SetOp(_handle, 9, 1);
                Task.Delay(plcConfig.TuiHeUpDelay).Wait();
                while (!TuiHeUpXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
            else if (!b && TuiHeUpXH) //下
            {
                LiWi.Shell.PMC_SetOp(_handle, 9, 0);
                Task.Delay(plcConfig.TuiHeUpDelay).Wait();
                while (!TuiHeDownXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
        }
        private void TuiHeOut(bool b)
        {
            int i = 0;
            if (b)  //上
            {
                LiWi.Shell.PMC_SetOp(_handle, 4, 1);
                Task.Delay(plcConfig.TuiHeOutDelay).Wait();
            }
            else if (!b) //下
            {
                LiWi.Shell.PMC_SetOp(_handle, 4, 0);
                Task.Delay(plcConfig.TuiHeOutDelay).Wait();
                while (!TuiHeHuiXH)
                {
                    Task.Delay(1).Wait();
                    i += 1;
                    if (i > 2000)
                        return;
                }
            }
        }
        #endregion
        #endregion

        #region WaitTimeout
        public CancellationTokenSource CTS { get; set; } = new CancellationTokenSource();
        public delegate void TimeOutDelegate();
        private int timeout = 0;
        private void WaitTimeout(int waitTime, string msg = "", TimeOutDelegate timeOutDelegate = null)
        {
            // 检查是否请求取消

            CTS.Token.ThrowIfCancellationRequested();
            Task.Delay(1).Wait();
            timeout += 1;
            if (timeout > waitTime)
            {
                CTS.Cancel();
                if (timeOutDelegate != null)
                    timeOutDelegate();
                eventAggregator.GetEvent<PLCRunMsgEvent>().Publish(new RunMsgModel($"等待超时:{msg}", "Red"));
            }
        } 
        #endregion
    }
}
